package com.weic.easycache.utils;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;

import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.Environment;
import android.os.Looper;

import com.weic.easycache.L;
import com.weic.easycache.framework.AbsApp;

public class CrashHandler {
	private static final String LOG_TAG = "CrashHandler";

	private static boolean handleOutOfMemoryError = false;
	private static boolean handleNullPointerException = false;

	private static final UncaughtExceptionHandler mUncaughtExceptionHandler = new UncaughtExceptionHandler();

	public static void makeDumpHprofData() {
		try {
			String path = Environment.getExternalStorageDirectory().getAbsolutePath()+"/currentdump"+getDateFormat().format(new Date())+".hprof";
			android.os.Debug.dumpHprofData(path);
			L.i(LOG_TAG, "生成内存快照："+path);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**拦截所有线程的所有异常。作该操作的主要原因：如果想在某个特定的时刻对某些线程进行拦截，很有可能无法在设置完handler的时刻立即拦截到。因此通常进行全局的拦截**/
	public static void startCaughtAllException(boolean currentThread, boolean handle) {
		CatchOutOfMemoryError.start(currentThread, handle);
		CatchNullPointerException.start(currentThread, handle);
	}

	public static class CatchOutOfMemoryError {
		public static void start(boolean currentThread, boolean handle) {
			handleOutOfMemoryError = handle;
			setDefaultHandler(currentThread);
		}
	}

	public static class CatchNullPointerException {
		public static void start(boolean currentThread, boolean handle) {
			handleNullPointerException = handle;
			setDefaultHandler(currentThread);
		}
	}

	public static void setDefaultHandler(boolean currentThread) {
		if(currentThread) {
			Thread.currentThread().setUncaughtExceptionHandler(mUncaughtExceptionHandler);
		}else {
			Thread.setDefaultUncaughtExceptionHandler(mUncaughtExceptionHandler);
		}
	}

	private static class UncaughtExceptionHandler implements Thread.UncaughtExceptionHandler {
		@Override
		public void uncaughtException(Thread thread, Throwable e) {
			Class<?> clazz = e.getClass();
			L.e(LOG_TAG, "拦截异常："+clazz.getName()+"，线程："+thread.getName(), e);
			if(handleOutOfMemoryError && clazz.equals(OutOfMemoryError.class)) {
				makeDumpHprofData();
			}else if(handleNullPointerException && clazz.equals(NullPointerException.class)) {

			}
			//android.os.Process.killProcess(android.os.Process.myPid());
			System.exit(2);
		}
	}

	private static SimpleDateFormat dateFormat;
	private static SimpleDateFormat getDateFormat() {
		if(dateFormat == null) dateFormat = new SimpleDateFormat("yyyyMMddHHmmss", Locale.CHINA);
		return dateFormat;
	}

	private static class UncaughtExceptionHandler2 implements Thread.UncaughtExceptionHandler {
		public void uncaughtException(Thread t, Throwable e) {
			L.e(this, e);
			if (t.getId() == Looper.getMainLooper().getThread().getId()) {
				if (isInHomeActivity()) {
					if (isCurrentlyForgeGround()) new XxxThread(this).start();
				}
				new LogThread(this).start();
			}
			try {
				Thread.sleep(2000);
				((AlarmManager)getApp().getSystemService(Context.ALARM_SERVICE)).set(AlarmManager.RTC, System.currentTimeMillis() + 10,
						PendingIntent.getActivity(getApp(), 0, new Intent(getApp(), getHomeActivityClass()), PendingIntent.FLAG_ONE_SHOT));
				System.exit(2);
			} catch (InterruptedException e1) {
				try {
					Thread.sleep(2000);
					System.exit(1);
				} catch (InterruptedException e2) {
					android.os.Process.killProcess(android.os.Process.myPid());
				}
			}
		}
	}

	private static Context getApp() {
		return AbsApp.get();
	}

	private static boolean isInHomeActivity() {
		// TODO Auto-generated method stub
		return false;
	}

	private static boolean isCurrentlyForgeGround() {
		// TODO Auto-generated method stub
		return false;
	}

	private static Class<?> getHomeActivityClass() {
		// TODO Auto-generated method stub
		return null;
	}

	private static class LogThread extends Thread {
		private UncaughtExceptionHandler2 handler;

		public LogThread(UncaughtExceptionHandler2 h) {
			handler = h;
		}

		@Override
		public void run() {
			//TODO ...
		}
	}

	private static class XxxThread extends Thread {
		private UncaughtExceptionHandler2 handler;

		public XxxThread(UncaughtExceptionHandler2 h) {
			handler = h;
		}

		@Override
		public void run() {
			//TODO ...
		}
	}
}